/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package fterms.argumentation;

import fterms.FeatureTerm;
import fterms.exceptions.FeatureTermException;
import fterms.learning.Rule;
import java.util.LinkedList;
import java.util.List;
import util.Pair;

/**
 *
 * @author santi
 */
public class ArgumentationState {
    List<Pair<String,ArgumentationTree>> m_baseArguments = new LinkedList<Pair<String,ArgumentationTree>>();
    List<Pair<String,ArgumentationTree>> m_retractedArguments = new LinkedList<Pair<String,ArgumentationTree>>();

    public ArgumentationState() {
        
    }

    public ArgumentationState(ArgumentationState as) {
        for(Pair<String,ArgumentationTree> p:as.m_baseArguments) {
            m_baseArguments.add(new Pair<String,ArgumentationTree>(p.m_a,p.m_b.clone()));
        }
        for(Pair<String,ArgumentationTree> p:as.m_retractedArguments) {
            m_retractedArguments.add(new Pair<String,ArgumentationTree>(p.m_a,p.m_b.clone()));
        }
    }

    public void addNewRoot(String agent,Argument root) {
        m_baseArguments.add(new Pair<String,ArgumentationTree>(agent,new ArgumentationTree(root)));
    }

    public List<FeatureTerm> getExamples() {
        List<FeatureTerm> examples = new LinkedList<FeatureTerm>();
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            examples.addAll(aNode.m_b.getExamples());
        }
        return examples;
    }

    public List<Argument> getRoots(String agent) {
        List<Argument> roots = new LinkedList<Argument>();
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            if (aNode.m_a.equals(agent)) {
                roots.add(aNode.m_b.getRoot());
            }
        }
        return roots;
    }

    public List<ArgumentationTree> getTrees() {
        List<ArgumentationTree> trees = new LinkedList<ArgumentationTree>();
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            trees.add(aNode.m_b);
        }
        return trees;
    }

    public List<ArgumentationTree> getRetractedTrees() {
        List<ArgumentationTree> trees = new LinkedList<ArgumentationTree>();
        for(Pair<String,ArgumentationTree> aNode:m_retractedArguments) {
            trees.add(aNode.m_b);
        }
        return trees;
    }

    public List<ArgumentationTree> getAllTrees() {
        List<ArgumentationTree> trees = new LinkedList<ArgumentationTree>();
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            trees.add(aNode.m_b);
        }
        for(Pair<String,ArgumentationTree> aNode:m_retractedArguments) {
            trees.add(aNode.m_b);
        }
        return trees;
    }

    public List<ArgumentationTree> getTrees(String agent) {
        List<ArgumentationTree> trees = new LinkedList<ArgumentationTree>();
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            if (aNode.m_a.equals(agent)) {
                trees.add(aNode.m_b);
            }
        }
        return trees;
    }

    public void retractRoot(Argument a) {
        List<Pair<String,ArgumentationTree>> toDelete = new LinkedList <Pair<String,ArgumentationTree>>();
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            if (aNode.m_b.getRoot()==a) toDelete.add(aNode);
        }
        m_baseArguments.removeAll(toDelete);
        m_retractedArguments.addAll(toDelete);
    }

    public List<Pair<Argument,ArgumentationTree>> getUnacceptable(String name, ArgumentAcceptability aa) throws FeatureTermException {
        List<Pair<Argument,ArgumentationTree>> args = new LinkedList<Pair<Argument,ArgumentationTree>>();
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            if (!aNode.m_a.equals(name) && !aNode.m_b.defeatedP()) {
                List<Argument> defenders = aNode.m_b.getDefenders();
                System.out.println(defenders.size() + " defenders for A"+aNode.m_b.getRoot().m_ID+" generated by " + aNode.m_a);
                if (defenders.size()==0) {
                    System.err.println("te llamo trigo por no llamarte rodrigo!");
                    System.err.println(aNode.m_b);
                }
                for(Argument a:defenders) {
                    if (!aa.accepted(a))
                        args.add(new Pair<Argument,ArgumentationTree>(a,aNode.m_b));
                }
            }
        }
        return args;
    }

        public List<Pair<Argument,ArgumentationTree>> getAcceptable(String name, ArgumentAcceptability aa) throws FeatureTermException {
        List<Pair<Argument,ArgumentationTree>> args = new LinkedList<Pair<Argument,ArgumentationTree>>();
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            if (!aNode.m_a.equals(name)) {
                List<Argument> defenders = aNode.m_b.getDefenders();
                for(Argument a:defenders) {
                    if (aa.accepted(a))
                        args.add(new Pair<Argument,ArgumentationTree>(a,aNode.m_b));
                }
            }
        }
        return args;
    }


    public List<Argument> getSettled() {
        List<Argument> args = new LinkedList<Argument>();
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            for(Argument a:aNode.m_b.getRuleArguments()) {
                if (aNode.m_b.settledP(a) && !aNode.m_b.defeatedP(a)) {
                    args.add(a);
                }
            }
        }
        for(Pair<String,ArgumentationTree> aNode:m_retractedArguments) {
            for(Argument a:aNode.m_b.getRuleArguments()) {
                if (aNode.m_b.settledP(a) && !aNode.m_b.defeatedP(a)) {
                    args.add(a);
                }
            }
        }
        return args;
    }

    public List<ArgumentationTree> getDefeatedUnsettled(String name) {
        List<ArgumentationTree> args = new LinkedList<ArgumentationTree>();
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            if (aNode.m_a.equals(name) && aNode.m_b.defeatedP() &&
                !aNode.m_b.settledP(aNode.m_b.getRoot())) {
                args.add(aNode.m_b);
            }
        }
        return args;
    }

    // This method is called when the agent "name" increases it's example base:
    public void unSettle(String name) {
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            if (aNode.m_a.equals(name)) aNode.m_b.unSettle();
        }
    }

    // Gets the root argument corresponding to the rule 'r', if it exists:
    public Argument getRoot(Rule r) {
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            if (aNode.m_b.getRoot().m_rule==r) return aNode.m_b.getRoot();
        }
        return null;
    }

    public void retractUnacceptable(String name, ArgumentAcceptability aa) throws FeatureTermException {
        List<Pair<String,ArgumentationTree>> toRetract = new LinkedList<Pair<String,ArgumentationTree>>();
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            if (aNode.m_b.retractUnacceptable(name, aa)) {
                // root retracted:
                toRetract.add(aNode);
            }
        }
        for(Pair<String,ArgumentationTree> aNode:toRetract) {
            m_baseArguments.remove(aNode);
            m_retractedArguments.add(aNode);
        }
    }

    public String toString() {
        String tmp = "Maintained:\n";
        for(Pair<String,ArgumentationTree> aNode:m_baseArguments) {
            tmp+=aNode.m_b.toString();
        }
        tmp+="Retracted:\n";
        for(Pair<String,ArgumentationTree> aNode:m_retractedArguments) {
            tmp+=aNode.m_b.toString();
        }
        return tmp;
    }


}
